ജാവാസ്ക്രിപ്റ്റിന്റെ അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളിലെ എറർ ഹാൻഡ്ലിംഗിനെക്കുറിച്ചുള്ള ഒരു സമ്പൂർണ്ണ ഗൈഡ്. എറർ പ്രൊപ്പഗേഷൻ, പ്രായോഗിക ഉദാഹരണങ്ങൾ, കാര്യക്ഷമമായ സ്ട്രീമിംഗ് ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കുന്നതിനുള്ള മികച്ച രീതികൾ എന്നിവ ഇതിൽ ഉൾപ്പെടുന്നു.
ജാവാസ്ക്രിപ്റ്റ് അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പർ എറർ പ്രൊപ്പഗേഷൻ: കരുത്തുറ്റ ആപ്ലിക്കേഷനുകൾക്കായി സ്ട്രീം എറർ ഹാൻഡ്ലിംഗ്
ആധുനിക ജാവാസ്ക്രിപ്റ്റ് ഡെവലപ്മെന്റിൽ, പ്രത്യേകിച്ച് ഡാറ്റാ സ്ട്രീമുകൾ കൈകാര്യം ചെയ്യുമ്പോൾ, അസിൻക്രണസ് പ്രോഗ്രാമിംഗ് സർവ്വവ്യാപിയായി മാറിയിരിക്കുന്നു. അസിങ്ക് ഇറ്ററേറ്ററുകളും അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനുകളും ഓരോ ഘടകങ്ങളായി ഡാറ്റ അസിൻക്രണസായി പ്രോസസ്സ് ചെയ്യുന്നതിനുള്ള ശക്തമായ ടൂളുകൾ നൽകുന്നു. എന്നിരുന്നാലും, കരുത്തുറ്റതും വിശ്വസനീയവുമായ ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കുന്നതിന് ഈ ഘടനകൾക്കുള്ളിൽ പിശകുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യേണ്ടത് അത്യാവശ്യമാണ്. ഈ സമഗ്രമായ ഗൈഡ് ജാവാസ്ക്രിപ്റ്റിന്റെ അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളിലെ എറർ പ്രൊപ്പഗേഷന്റെ സങ്കീർണ്ണതകൾ പര്യവേക്ഷണം ചെയ്യുകയും സ്ട്രീമിംഗ് ആപ്ലിക്കേഷനുകളിലെ പിശകുകൾ ഫലപ്രദമായി കൈകാര്യം ചെയ്യുന്നതിനുള്ള പ്രായോഗിക ഉദാഹരണങ്ങളും മികച്ച രീതികളും നൽകുകയും ചെയ്യുന്നു.
അസിങ്ക് ഇറ്ററേറ്ററുകളും അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനുകളും മനസ്സിലാക്കുന്നു
എറർ ഹാൻഡ്ലിംഗിലേക്ക് കടക്കുന്നതിന് മുമ്പ്, അസിങ്ക് ഇറ്ററേറ്ററുകളുടെയും അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനുകളുടെയും അടിസ്ഥാന ആശയങ്ങൾ നമുക്ക് ഹ്രസ്വമായി അവലോകനം ചെയ്യാം.
അസിങ്ക് ഇറ്ററേറ്ററുകൾ
ഒരു അസിങ്ക് ഇറ്ററേറ്റർ എന്നത് next() മെത്തേഡ് നൽകുന്ന ഒരു ഒബ്ജക്റ്റാണ്. ഇത് value, done എന്നീ പ്രോപ്പർട്ടികളുള്ള ഒരു ഒബ്ജക്റ്റിലേക്ക് റിസോൾവ് ചെയ്യുന്ന ഒരു പ്രോമിസ് നൽകുന്നു. value പ്രോപ്പർട്ടി ശ്രേണിയിലെ അടുത്ത മൂല്യം സൂക്ഷിക്കുന്നു, done പ്രോപ്പർട്ടി ഇറ്ററേറ്റർ പൂർത്തിയായോ എന്ന് സൂചിപ്പിക്കുന്നു.
ഉദാഹരണം:
async function* createAsyncIterator(data) {
for (const item of data) {
await new Promise(resolve => setTimeout(resolve, 50)); // Simulate asynchronous operation
yield item;
}
}
const asyncIterator = createAsyncIterator([1, 2, 3]);
async function consumeIterator() {
let result = await asyncIterator.next();
while (!result.done) {
console.log(result.value);
result = await asyncIterator.next();
}
}
consumeIterator(); // Output: 1, 2, 3 (with delays)
അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനുകൾ
ഒരു അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷൻ ഒരു അസിങ്ക് ഇറ്ററേറ്റർ നൽകുന്ന ഒരു പ്രത്യേക തരം ഫംഗ്ഷനാണ്. ഇത് അസിൻക്രണസായി മൂല്യങ്ങൾ നിർമ്മിക്കാൻ yield കീവേഡ് ഉപയോഗിക്കുന്നു.
ഉദാഹരണം:
async function* generateSequence(start, end) {
for (let i = start; i <= end; i++) {
await new Promise(resolve => setTimeout(resolve, 100)); // Simulate asynchronous operation
yield i;
}
}
async function consumeGenerator() {
for await (const num of generateSequence(1, 5)) {
console.log(num);
}
}
consumeGenerator(); // Output: 1, 2, 3, 4, 5 (with delays)
അസിങ്ക് സ്ട്രീമുകളിലെ എറർ ഹാൻഡ്ലിംഗിന്റെ വെല്ലുവിളി
അസിൻക്രണസ് സ്ട്രീമുകളിലെ എറർ ഹാൻഡ്ലിംഗ്, സിൻക്രണസ് കോഡുമായി താരതമ്യപ്പെടുത്തുമ്പോൾ സവിശേഷമായ വെല്ലുവിളികൾ ഉയർത്തുന്നു. പരമ്പരാഗത try/catch ബ്ലോക്കുകൾക്ക് പെട്ടെന്നുള്ള സിൻക്രണസ് സ്കോപ്പിൽ സംഭവിക്കുന്ന പിശകുകൾ മാത്രമേ കണ്ടെത്താൻ കഴിയൂ. ഒരു അസിങ്ക് ഇറ്ററേറ്ററിലോ ജനറേറ്ററിലോ ഉള്ള അസിൻക്രണസ് പ്രവർത്തനങ്ങൾ കൈകാര്യം ചെയ്യുമ്പോൾ, പിശകുകൾ വ്യത്യസ്ത സമയങ്ങളിൽ സംഭവിക്കാം, ഇതിന് എറർ പ്രൊപ്പഗേഷനായി കൂടുതൽ സങ്കീർണ്ണമായ ഒരു സമീപനം ആവശ്യമാണ്.
നിങ്ങൾ ഒരു റിമോട്ട് എപിഐയിൽ നിന്ന് ഡാറ്റ പ്രോസസ്സ് ചെയ്യുന്ന ഒരു സാഹചര്യം പരിഗണിക്കുക. നെറ്റ്വർക്ക് പരാജയം അല്ലെങ്കിൽ ഒരു സെർവർ-സൈഡ് പ്രശ്നം പോലുള്ള ഒരു പിശക് എപിഐ എപ്പോൾ വേണമെങ്കിലും നൽകിയേക്കാം. നിങ്ങളുടെ ആപ്ലിക്കേഷന് ഈ പിശകുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യാനും അവ ലോഗ് ചെയ്യാനും പ്രവർത്തനം വീണ്ടും ശ്രമിക്കാനോ ഒരു ഫാൾബാക്ക് മൂല്യം നൽകാനോ കഴിയേണ്ടതുണ്ട്.
അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളിൽ എറർ പ്രൊപ്പഗേഷനുള്ള തന്ത്രങ്ങൾ
അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളിൽ പിശകുകൾ ഫലപ്രദമായി കൈകാര്യം ചെയ്യാൻ നിരവധി തന്ത്രങ്ങൾ ഉപയോഗിക്കാം. ഏറ്റവും സാധാരണവും ഫലപ്രദവുമായ ചില ടെക്നിക്കുകൾ നമുക്ക് പര്യവേക്ഷണം ചെയ്യാം.
1. അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനിലെ Try/Catch ബ്ലോക്കുകൾ
അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനിലെ അസിൻക്രണസ് പ്രവർത്തനങ്ങൾ try/catch ബ്ലോക്കുകൾക്കുള്ളിൽ ഉൾപ്പെടുത്തുന്നത് ഏറ്റവും ലളിതമായ സമീപനങ്ങളിൽ ഒന്നാണ്. ജനറേറ്ററിന്റെ പ്രവർത്തന സമയത്ത് സംഭവിക്കുന്ന പിശകുകൾ കണ്ടെത്തി അതിനനുസരിച്ച് കൈകാര്യം ചെയ്യാൻ ഇത് നിങ്ങളെ അനുവദിക്കുന്നു.
ഉദാഹരണം:
async function* fetchData(urls) {
for (const url of urls) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
yield data;
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
// Optionally, yield a fallback value or re-throw the error
yield { error: error.message, url: url }; // Yield an error object
}
}
}
async function consumeData() {
for await (const item of fetchData(['https://example.com/data1', 'https://example.com/data2'])) {
if (item.error) {
console.warn(`Encountered an error for URL: ${item.url}, Error: ${item.error}`);
} else {
console.log('Received data:', item);
}
}
}
consumeData();
ഈ ഉദാഹരണത്തിൽ, fetchData ജനറേറ്റർ ഫംഗ്ഷൻ URL-കളുടെ ഒരു ലിസ്റ്റിൽ നിന്ന് ഡാറ്റ ലഭ്യമാക്കുന്നു. ഫെച്ച് ഓപ്പറേഷൻ സമയത്ത് ഒരു പിശക് സംഭവിച്ചാൽ, catch ബ്ലോക്ക് പിശക് ലോഗ് ചെയ്യുകയും ഒരു എറർ ഒബ്ജക്റ്റ് നൽകുകയും ചെയ്യുന്നു. ഉപഭോക്തൃ ഫംഗ്ഷൻ യീൽഡ് ചെയ്ത മൂല്യത്തിൽ error പ്രോപ്പർട്ടി പരിശോധിക്കുകയും അതനുസരിച്ച് കൈകാര്യം ചെയ്യുകയും ചെയ്യുന്നു. ഈ പാറ്റേൺ പിശകുകൾ പ്രാദേശികമായി കൈകാര്യം ചെയ്യപ്പെടുന്നുവെന്ന് ഉറപ്പാക്കുകയും സ്ട്രീം മുഴുവൻ തകരാറിലാകുന്നത് തടയുകയും ചെയ്യുന്നു.
2. എറർ ഹാൻഡ്ലിംഗിനായി `Promise.prototype.catch` ഉപയോഗിക്കുന്നു
അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനിൽ പ്രോമിസുകളിൽ .catch() മെത്തേഡ് ഉപയോഗിക്കുന്നത് മറ്റൊരു സാധാരണ ടെക്നിക്കാണ്. ഒരു പ്രോമിസിന്റെ റെസല്യൂഷൻ സമയത്ത് സംഭവിക്കുന്ന പിശകുകൾ കൈകാര്യം ചെയ്യാൻ ഇത് നിങ്ങളെ അനുവദിക്കുന്നു.
ഉദാഹരണം:
async function* fetchData(urls) {
for (const url of urls) {
const promise = fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.catch(error => {
console.error(`Error fetching data from ${url}:`, error);
return { error: error.message, url: url }; // Return an error object
});
yield await promise;
}
}
async function consumeData() {
for await (const item of fetchData(['https://example.com/data1', 'https://example.com/data2'])) {
if (item.error) {
console.warn(`Encountered an error for URL: ${item.url}, Error: ${item.error}`);
} else {
console.log('Received data:', item);
}
}
}
consumeData();
ഈ ഉദാഹരണത്തിൽ, ഫെച്ച് ഓപ്പറേഷൻ സമയത്ത് സംഭവിക്കുന്ന പിശകുകൾ കൈകാര്യം ചെയ്യാൻ .catch() മെത്തേഡ് ഉപയോഗിക്കുന്നു. ഒരു പിശക് സംഭവിച്ചാൽ, catch ബ്ലോക്ക് പിശക് ലോഗ് ചെയ്യുകയും ഒരു എറർ ഒബ്ജക്റ്റ് നൽകുകയും ചെയ്യുന്നു. ജനറേറ്റർ ഫംഗ്ഷൻ പ്രോമിസിന്റെ ഫലം നൽകുന്നു, അത് ഫെച്ച് ചെയ്ത ഡാറ്റയോ എറർ ഒബ്ജക്റ്റോ ആയിരിക്കും. ഈ സമീപനം പ്രോമിസ് റെസല്യൂഷൻ സമയത്ത് സംഭവിക്കുന്ന പിശകുകൾ കൈകാര്യം ചെയ്യുന്നതിന് വൃത്തിയുള്ളതും സംക്ഷിപ്തവുമായ മാർഗ്ഗം നൽകുന്നു.
3. ഒരു കസ്റ്റം എറർ ഹാൻഡ്ലിംഗ് ഹെൽപ്പർ ഫംഗ്ഷൻ നടപ്പിലാക്കുന്നു
കൂടുതൽ സങ്കീർണ്ണമായ എറർ ഹാൻഡ്ലിംഗ് സാഹചര്യങ്ങൾക്കായി, ഒരു കസ്റ്റം എറർ ഹാൻഡ്ലിംഗ് ഹെൽപ്പർ ഫംഗ്ഷൻ സൃഷ്ടിക്കുന്നത് പ്രയോജനകരമാണ്. ഈ ഫംഗ്ഷന് എറർ ഹാൻഡ്ലിംഗ് ലോജിക്ക് ഉൾക്കൊള്ളാനും നിങ്ങളുടെ ആപ്ലിക്കേഷനിലുടനീളം പിശകുകൾ കൈകാര്യം ചെയ്യാൻ സ്ഥിരതയുള്ള ഒരു മാർഗ്ഗം നൽകാനും കഴിയും.
ഉദാഹരണം:
async function safeFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
return { error: error.message, url: url }; // Return an error object
}
}
async function* fetchData(urls) {
for (const url of urls) {
yield await safeFetch(url);
}
}
async function consumeData() {
for await (const item of fetchData(['https://example.com/data1', 'https://example.com/data2'])) {
if (item.error) {
console.warn(`Encountered an error for URL: ${item.url}, Error: ${item.error}`);
} else {
console.log('Received data:', item);
}
}
}
consumeData();
ഈ ഉദാഹരണത്തിൽ, safeFetch ഫംഗ്ഷൻ ഫെച്ച് ഓപ്പറേഷന്റെ എറർ ഹാൻഡ്ലിംഗ് ലോജിക്ക് ഉൾക്കൊള്ളുന്നു. fetchData ജനറേറ്റർ ഫംഗ്ഷൻ ഓരോ URL-ൽ നിന്നും ഡാറ്റ ലഭ്യമാക്കാൻ safeFetch ഫംഗ്ഷൻ ഉപയോഗിക്കുന്നു. ഈ സമീപനം കോഡ് പുനരുപയോഗവും പരിപാലനവും പ്രോത്സാഹിപ്പിക്കുന്നു.
4. അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകൾ ഉപയോഗിക്കുന്നു: `map`, `filter`, `reduce`, എറർ ഹാൻഡ്ലിംഗ്
ജാവാസ്ക്രിപ്റ്റിന്റെ അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകൾ (`map`, `filter`, `reduce`, തുടങ്ങിയവ) അസിങ്ക് സ്ട്രീമുകൾ രൂപാന്തരപ്പെടുത്താനും പ്രോസസ്സ് ചെയ്യാനും സൗകര്യപ്രദമായ വഴികൾ നൽകുന്നു. ഈ ഹെൽപ്പറുകൾ ഉപയോഗിക്കുമ്പോൾ, പിശകുകൾ എങ്ങനെയാണ് പ്രൊപ്പഗേറ്റ് ചെയ്യപ്പെടുന്നതെന്നും അവ എങ്ങനെ ഫലപ്രദമായി കൈകാര്യം ചെയ്യണമെന്നും മനസ്സിലാക്കേണ്ടത് അത്യാവശ്യമാണ്.
a) `map` -ലെ എറർ ഹാൻഡ്ലിംഗ്
map ഹെൽപ്പർ അസിങ്ക് സ്ട്രീമിലെ ഓരോ ഘടകത്തിനും ഒരു ട്രാൻസ്ഫോർമേഷൻ ഫംഗ്ഷൻ പ്രയോഗിക്കുന്നു. ട്രാൻസ്ഫോർമേഷൻ ഫംഗ്ഷൻ ഒരു പിശക് എറിഞ്ഞാൽ, പിശക് ഉപഭോക്താവിലേക്ക് പ്രൊപ്പഗേറ്റ് ചെയ്യപ്പെടുന്നു.
ഉദാഹരണം:
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
async function consumeData() {
try {
const asyncIterable = generateNumbers(5);
const mappedIterable = asyncIterable.map(async (num) => {
if (num === 3) {
throw new Error('Error processing number 3');
}
return num * 2;
});
for await (const item of mappedIterable) {
console.log(item);
}
} catch (error) {
console.error('An error occurred:', error);
}
}
consumeData(); // Output: 2, 4, An error occurred: Error: Error processing number 3
ഈ ഉദാഹരണത്തിൽ, 3 എന്ന നമ്പർ പ്രോസസ്സ് ചെയ്യുമ്പോൾ ട്രാൻസ്ഫോർമേഷൻ ഫംഗ്ഷൻ ഒരു പിശക് എറിയുന്നു. consumeData ഫംഗ്ഷനിലെ catch ബ്ലോക്ക് പിശക് കണ്ടെത്തുന്നു. പിശക് ഇറ്ററേഷൻ നിർത്തുന്നു എന്നത് ശ്രദ്ധിക്കുക.
b) `filter` -ലെ എറർ ഹാൻഡ്ലിംഗ്
filter ഹെൽപ്പർ ഒരു പ്രെഡിക്കേറ്റ് ഫംഗ്ഷനെ അടിസ്ഥാനമാക്കി അസിങ്ക് സ്ട്രീമിലെ ഘടകങ്ങളെ ഫിൽട്ടർ ചെയ്യുന്നു. പ്രെഡിക്കേറ്റ് ഫംഗ്ഷൻ ഒരു പിശക് എറിഞ്ഞാൽ, പിശക് ഉപഭോക്താവിലേക്ക് പ്രൊപ്പഗേറ്റ് ചെയ്യപ്പെടുന്നു.
ഉദാഹരണം:
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
async function consumeData() {
try {
const asyncIterable = generateNumbers(5);
const filteredIterable = asyncIterable.filter(async (num) => {
if (num === 3) {
throw new Error('Error filtering number 3');
}
return num % 2 === 0;
});
for await (const item of filteredIterable) {
console.log(item);
}
} catch (error) {
console.error('An error occurred:', error);
}
}
consumeData(); // Output: An error occurred: Error: Error filtering number 3
ഈ ഉദാഹരണത്തിൽ, 3 എന്ന നമ്പർ പ്രോസസ്സ് ചെയ്യുമ്പോൾ പ്രെഡിക്കേറ്റ് ഫംഗ്ഷൻ ഒരു പിശക് എറിയുന്നു. consumeData ഫംഗ്ഷനിലെ catch ബ്ലോക്ക് പിശക് കണ്ടെത്തുന്നു.
c) `reduce` -ലെ എറർ ഹാൻഡ്ലിംഗ്
reduce ഹെൽപ്പർ ഒരു റിഡ്യൂസർ ഫംഗ്ഷൻ ഉപയോഗിച്ച് അസിങ്ക് സ്ട്രീമിനെ ഒരൊറ്റ മൂല്യത്തിലേക്ക് ചുരുക്കുന്നു. റിഡ്യൂസർ ഫംഗ്ഷൻ ഒരു പിശക് എറിഞ്ഞാൽ, പിശക് ഉപഭോക്താവിലേക്ക് പ്രൊപ്പഗേറ്റ് ചെയ്യപ്പെടുന്നു.
ഉദാഹരണം:
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
async function consumeData() {
try {
const asyncIterable = generateNumbers(5);
const sum = await asyncIterable.reduce(async (acc, num) => {
if (num === 3) {
throw new Error('Error reducing number 3');
}
return acc + num;
}, 0);
console.log('Sum:', sum);
} catch (error) {
console.error('An error occurred:', error);
}
}
consumeData(); // Output: An error occurred: Error: Error reducing number 3
ഈ ഉദാഹരണത്തിൽ, 3 എന്ന നമ്പർ പ്രോസസ്സ് ചെയ്യുമ്പോൾ റിഡ്യൂസർ ഫംഗ്ഷൻ ഒരു പിശക് എറിയുന്നു. consumeData ഫംഗ്ഷനിലെ catch ബ്ലോക്ക് പിശക് കണ്ടെത്തുന്നു.
5. `process.on('unhandledRejection')` (Node.js) അല്ലെങ്കിൽ `window.addEventListener('unhandledrejection')` (ബ്രൗസറുകൾ) ഉപയോഗിച്ചുള്ള ഗ്ലോബൽ എറർ ഹാൻഡ്ലിംഗ്
അസിങ്ക് ഇറ്ററേറ്ററുകൾക്ക് മാത്രമുള്ളതല്ലെങ്കിലും, ഗ്ലോബൽ എറർ ഹാൻഡ്ലിംഗ് മെക്കാനിസങ്ങൾ ക്രമീകരിക്കുന്നത് നിങ്ങളുടെ സ്ട്രീമുകളിൽ സംഭവിക്കാനിടയുള്ള കൈകാര്യം ചെയ്യാത്ത പ്രോമിസ് റിജക്ഷനുകൾക്ക് ഒരു സുരക്ഷാ വലയം നൽകും. Node.js എൻവയോൺമെന്റുകളിൽ ഇത് പ്രത്യേകിച്ചും പ്രധാനമാണ്.
Node.js ഉദാഹരണം:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Optionally, perform cleanup or exit the process
});
async function* generateNumbers(n) {
for (let i = 1; i <= n; i++) {
if (i === 3) {
throw new Error('Simulated Error'); // This will cause an unhandled rejection if not caught locally
}
yield i;
}
}
async function main() {
const iterator = generateNumbers(5);
for await (const num of iterator) {
console.log(num);
}
}
main(); // Will trigger 'unhandledRejection' if the error inside generator isn't handled.
ബ്രൗസർ ഉദാഹരണം:
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled rejection:', event.reason, event.promise);
// You can log the error or display a user-friendly message here.
});
async function fetchData(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); // Might cause unhandled rejection if `fetchData` isn't wrapped in try/catch
}
return response.json();
}
async function processData() {
const data = await fetchData('https://example.com/api/nonexistent'); // URL likely to cause an error.
console.log(data);
}
processData();
പ്രധാന പരിഗണനകൾ:
- ഡീബഗ്ഗിംഗ്: കൈകാര്യം ചെയ്യാത്ത റിജക്ഷനുകൾ ലോഗ് ചെയ്യുന്നതിനും ഡീബഗ്ഗ് ചെയ്യുന്നതിനും ഗ്ലോബൽ ഹാൻഡ്ലറുകൾ വിലപ്പെട്ടതാണ്.
- ശുചീകരണം: ആപ്ലിക്കേഷൻ ക്രാഷാകുന്നതിനുമുമ്പ് ശുചീകരണ പ്രവർത്തനങ്ങൾ നടത്താൻ നിങ്ങൾക്ക് ഈ ഹാൻഡ്ലറുകൾ ഉപയോഗിക്കാം.
- ക്രാഷുകൾ തടയുക: അവ പിശകുകൾ ലോഗ് ചെയ്യുമെങ്കിലും, പിശക് അടിസ്ഥാനപരമായി ലോജിക്കിനെ തകർക്കുകയാണെങ്കിൽ ആപ്ലിക്കേഷൻ ക്രാഷാകുന്നത് തടയുന്നില്ല. അതിനാൽ, അസിങ്ക് സ്ട്രീമുകളിലെ പ്രാദേശിക എറർ ഹാൻഡ്ലിംഗ് എല്ലായ്പ്പോഴും പ്രാഥമിക പ്രതിരോധമാണ്.
അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളിലെ എറർ ഹാൻഡ്ലിംഗിനുള്ള മികച്ച രീതികൾ
നിങ്ങളുടെ അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളിൽ കരുത്തുറ്റ എറർ ഹാൻഡ്ലിംഗ് ഉറപ്പാക്കാൻ, ഇനിപ്പറയുന്ന മികച്ച രീതികൾ പരിഗണിക്കുക:
- എറർ ഹാൻഡ്ലിംഗ് പ്രാദേശികവൽക്കരിക്കുക: പിശകുകൾ അവയുടെ ഉറവിടത്തോട് കഴിയുന്നത്ര അടുത്ത് കൈകാര്യം ചെയ്യുക. അസിൻക്രണസ് പ്രവർത്തനങ്ങൾക്കിടയിൽ സംഭവിക്കുന്ന പിശകുകൾ കണ്ടെത്താൻ അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനിൽ
try/catchബ്ലോക്കുകളോ.catch()മെത്തേഡുകളോ ഉപയോഗിക്കുക. - ഫാൾബാക്ക് മൂല്യങ്ങൾ നൽകുക: ഒരു പിശക് സംഭവിക്കുമ്പോൾ, സ്ട്രീം മുഴുവനും ക്രാഷാകുന്നത് തടയാൻ ഒരു ഫാൾബാക്ക് മൂല്യമോ ഡിഫോൾട്ട് മൂല്യമോ നൽകുന്നത് പരിഗണിക്കുക. ചില ഘടകങ്ങൾ അസാധുവാണെങ്കിൽ പോലും സ്ട്രീം പ്രോസസ്സ് ചെയ്യുന്നത് തുടരാൻ ഇത് ഉപഭോക്താവിനെ അനുവദിക്കുന്നു.
- പിശകുകൾ ലോഗ് ചെയ്യുക: ഡീബഗ്ഗിംഗ് സുഗമമാക്കുന്നതിന് മതിയായ വിശദാംശങ്ങളോടെ പിശകുകൾ ലോഗ് ചെയ്യുക. URL, പിശക് സന്ദേശം, സ്റ്റാക്ക് ട്രെയ്സ് തുടങ്ങിയ വിവരങ്ങൾ ഉൾപ്പെടുത്തുക.
- പ്രവർത്തനങ്ങൾ വീണ്ടും ശ്രമിക്കുക: നെറ്റ്വർക്ക് പരാജയങ്ങൾ പോലുള്ള താൽക്കാലിക പിശകുകൾക്ക്, ഒരു ചെറിയ കാലതാമസത്തിന് ശേഷം പ്രവർത്തനം വീണ്ടും ശ്രമിക്കുന്നത് പരിഗണിക്കുക. അനന്തമായ ലൂപ്പുകൾ ഒഴിവാക്കാൻ പരമാവധി ശ്രമങ്ങളുടെ എണ്ണമുള്ള ഒരു റിട്രൈ മെക്കാനിസം നടപ്പിലാക്കുക.
- ഒരു കസ്റ്റം എറർ ഹാൻഡ്ലിംഗ് ഹെൽപ്പർ ഫംഗ്ഷൻ ഉപയോഗിക്കുക: കോഡ് പുനരുപയോഗവും പരിപാലനവും പ്രോത്സാഹിപ്പിക്കുന്നതിന് ഒരു കസ്റ്റം ഹെൽപ്പർ ഫംഗ്ഷനിൽ എറർ ഹാൻഡ്ലിംഗ് ലോജിക്ക് ഉൾക്കൊള്ളിക്കുക.
- ഗ്ലോബൽ എറർ ഹാൻഡ്ലിംഗ് പരിഗണിക്കുക: കൈകാര്യം ചെയ്യാത്ത പ്രോമിസ് റിജക്ഷനുകൾ പിടിക്കാൻ Node.js-ലെ
process.on('unhandledRejection')പോലുള്ള ഗ്ലോബൽ എറർ ഹാൻഡ്ലിംഗ് മെക്കാനിസങ്ങൾ നടപ്പിലാക്കുക. എന്നിരുന്നാലും, പ്രാഥമിക പ്രതിരോധമായി പ്രാദേശിക എറർ ഹാൻഡ്ലിംഗിനെ ആശ്രയിക്കുക. - ഭംഗിയായ ഷട്ട്ഡൗൺ: സെർവർ-സൈഡ് ആപ്ലിക്കേഷനുകളിൽ, ഡാറ്റാ നഷ്ടം തടയുന്നതിനും വൃത്തിയുള്ള ഷട്ട്ഡൗൺ ഉറപ്പാക്കുന്നതിനും നിങ്ങളുടെ അസിങ്ക് സ്ട്രീം പ്രോസസ്സിംഗ് കോഡ്
SIGINT(Ctrl+C),SIGTERMപോലുള്ള സിഗ്നലുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യുന്നുവെന്ന് ഉറപ്പാക്കുക. ഇതിൽ റിസോഴ്സുകൾ (ഡാറ്റാബേസ് കണക്ഷനുകൾ, ഫയൽ ഹാൻഡിലുകൾ, നെറ്റ്വർക്ക് കണക്ഷനുകൾ) അടയ്ക്കുന്നതും ശേഷിക്കുന്ന പ്രവർത്തനങ്ങൾ പൂർത്തിയാക്കുന്നതും ഉൾപ്പെടുന്നു. - നിരീക്ഷണവും മുന്നറിയിപ്പും: നിങ്ങളുടെ അസിങ്ക് സ്ട്രീം പ്രോസസ്സിംഗ് കോഡിലെ പിശകുകൾ കണ്ടെത്താനും പ്രതികരിക്കാനും നിരീക്ഷണ, മുന്നറിയിപ്പ് സംവിധാനങ്ങൾ നടപ്പിലാക്കുക. ഇത് ഉപയോക്താക്കളെ ബാധിക്കുന്നതിനുമുമ്പ് പ്രശ്നങ്ങൾ തിരിച്ചറിയാനും പരിഹരിക്കാനും നിങ്ങളെ സഹായിക്കും.
പ്രായോഗിക ഉദാഹരണങ്ങൾ: യഥാർത്ഥ ലോക സാഹചര്യങ്ങളിലെ എറർ ഹാൻഡ്ലിംഗ്
അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകൾ ഉൾപ്പെടുന്ന യഥാർത്ഥ ലോക സാഹചര്യങ്ങളിലെ എറർ ഹാൻഡ്ലിംഗിന്റെ ചില പ്രായോഗിക ഉദാഹരണങ്ങൾ നമുക്ക് പരിശോധിക്കാം.
ഉദാഹരണം 1: ഫാൾബാക്ക് മെക്കാനിസം ഉപയോഗിച്ച് ഒന്നിലധികം എപിഐകളിൽ നിന്നുള്ള ഡാറ്റ പ്രോസസ്സ് ചെയ്യുന്നു
നിങ്ങൾക്ക് ഒന്നിലധികം എപിഐകളിൽ നിന്ന് ഡാറ്റ ലഭ്യമാക്കണമെന്ന് സങ്കൽപ്പിക്കുക. ഒരു എപിഐ പരാജയപ്പെട്ടാൽ, നിങ്ങൾ ഒരു ഫാൾബാക്ക് എപിഐ ഉപയോഗിക്കാനോ ഒരു ഡിഫോൾട്ട് മൂല്യം നൽകാനോ ആഗ്രഹിക്കുന്നു.
async function safeFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
return null; // Indicate failure
}
}
async function* fetchDataWithFallback(apiUrls, fallbackUrl) {
for (const apiUrl of apiUrls) {
let data = await safeFetch(apiUrl);
if (data === null) {
console.log(`Attempting fallback for ${apiUrl}`);
data = await safeFetch(fallbackUrl);
if (data === null) {
console.warn(`Fallback also failed for ${apiUrl}. Returning default value.`);
yield { error: `Failed to fetch data from ${apiUrl} and fallback.` };
continue; // Skip to the next URL
}
}
yield data;
}
}
async function processData() {
const apiUrls = ['https://api.example.com/data1', 'https://api.nonexistent.com/data2', 'https://api.example.com/data3'];
const fallbackUrl = 'https://backup.example.com/default_data';
for await (const item of fetchDataWithFallback(apiUrls, fallbackUrl)) {
if (item.error) {
console.warn(`Error processing data: ${item.error}`);
} else {
console.log('Processed data:', item);
}
}
}
processData();
ഈ ഉദാഹരണത്തിൽ, fetchDataWithFallback ജനറേറ്റർ ഫംഗ്ഷൻ എപിഐകളുടെ ഒരു ലിസ്റ്റിൽ നിന്ന് ഡാറ്റ ലഭ്യമാക്കാൻ ശ്രമിക്കുന്നു. ഒരു എപിഐ പരാജയപ്പെട്ടാൽ, അത് ഒരു ഫാൾബാക്ക് എപിഐയിൽ നിന്ന് ഡാറ്റ ലഭ്യമാക്കാൻ ശ്രമിക്കുന്നു. ഫാൾബാക്ക് എപിഐയും പരാജയപ്പെട്ടാൽ, അത് ഒരു മുന്നറിയിപ്പ് ലോഗ് ചെയ്യുകയും ഒരു എറർ ഒബ്ജക്റ്റ് നൽകുകയും ചെയ്യുന്നു. ഉപഭോക്തൃ ഫംഗ്ഷൻ അതനുസരിച്ച് പിശക് കൈകാര്യം ചെയ്യുന്നു.
ഉദാഹരണം 2: എറർ ഹാൻഡ്ലിംഗോടുകൂടിയ റേറ്റ് ലിമിറ്റിംഗ്
എപിഐകളുമായി, പ്രത്യേകിച്ച് മൂന്നാം കക്ഷി എപിഐകളുമായി സംവദിക്കുമ്പോൾ, എപിഐയുടെ ഉപയോഗ പരിധികൾ കവിയുന്നത് ഒഴിവാക്കാൻ നിങ്ങൾ പലപ്പോഴും റേറ്റ് ലിമിറ്റിംഗ് നടപ്പിലാക്കേണ്ടതുണ്ട്. റേറ്റ് ലിമിറ്റ് പിശകുകൾ കൈകാര്യം ചെയ്യുന്നതിന് ശരിയായ എറർ ഹാൻഡ്ലിംഗ് അത്യാവശ്യമാണ്.
const rateLimit = 5; // Number of requests per second
let requestCount = 0;
let lastRequestTime = 0;
async function throttledFetch(url) {
const now = Date.now();
if (requestCount >= rateLimit && now - lastRequestTime < 1000) {
const delay = 1000 - (now - lastRequestTime);
console.log(`Rate limit exceeded. Waiting ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
try {
const response = await fetch(url);
if (response.status === 429) { // Rate limit exceeded
console.warn('Rate limit exceeded. Retrying after a delay...');
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait longer
return throttledFetch(url); // Retry
}
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
requestCount++;
lastRequestTime = Date.now();
return data;
} catch (error) {
console.error(`Error fetching ${url}:`, error);
throw error; // Re-throw the error after logging
}
}
async function* fetchUrls(urls) {
for (const url of urls) {
try {
yield await throttledFetch(url);
} catch (err) {
console.error(`Failed to fetch URL ${url} after retries. Skipping.`);
yield { error: `Failed to fetch ${url}` }; // Signal error to consumer
}
}
}
async function consumeData() {
const urls = ['https://api.example.com/resource1', 'https://api.example.com/resource2', 'https://api.example.com/resource3'];
for await (const item of fetchUrls(urls)) {
if (item.error) {
console.warn(`Error: ${item.error}`);
} else {
console.log('Data:', item);
}
}
}
consumeData();
ഈ ഉദാഹരണത്തിൽ, throttledFetch ഫംഗ്ഷൻ ഒരു സെക്കൻഡിനുള്ളിൽ നടത്തിയ അഭ്യർത്ഥനകളുടെ എണ്ണം ട്രാക്ക് ചെയ്തുകൊണ്ട് റേറ്റ് ലിമിറ്റിംഗ് നടപ്പിലാക്കുന്നു. റേറ്റ് ലിമിറ്റ് കവിഞ്ഞാൽ, അടുത്ത അഭ്യർത്ഥന നടത്തുന്നതിന് മുമ്പ് അത് ഒരു ചെറിയ കാലതാമസത്തിനായി കാത്തിരിക്കുന്നു. ഒരു 429 (Too Many Requests) പിശക് ലഭിച്ചാൽ, അത് കൂടുതൽ നേരം കാത്തിരുന്ന് അഭ്യർത്ഥന വീണ്ടും ശ്രമിക്കുന്നു. പിശകുകൾ ലോഗ് ചെയ്യുകയും കോളർ കൈകാര്യം ചെയ്യുന്നതിനായി വീണ്ടും എറിയുകയും ചെയ്യുന്നു.
ഉപസംഹാരം
അസിൻക്രണസ് പ്രോഗ്രാമിംഗിന്റെ ഒരു നിർണായക വശമാണ് എറർ ഹാൻഡ്ലിംഗ്, പ്രത്യേകിച്ച് അസിങ്ക് ഇറ്ററേറ്ററുകളും അസിങ്ക് ജനറേറ്റർ ഫംഗ്ഷനുകളും ഉപയോഗിച്ച് പ്രവർത്തിക്കുമ്പോൾ. എറർ പ്രൊപ്പഗേഷനുള്ള തന്ത്രങ്ങൾ മനസ്സിലാക്കുകയും മികച്ച രീതികൾ നടപ്പിലാക്കുകയും ചെയ്യുന്നതിലൂടെ, നിങ്ങൾക്ക് പിശകുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യുകയും അപ്രതീക്ഷിത ക്രാഷുകൾ തടയുകയും ചെയ്യുന്ന കരുത്തുറ്റതും വിശ്വസനീയവുമായ സ്ട്രീമിംഗ് ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കാൻ കഴിയും. പ്രാദേശിക എറർ ഹാൻഡ്ലിംഗിന് മുൻഗണന നൽകാനും, ഫാൾബാക്ക് മൂല്യങ്ങൾ നൽകാനും, പിശകുകൾ ഫലപ്രദമായി ലോഗ് ചെയ്യാനും, കൂടുതൽ പ്രതിരോധശേഷിക്കായി ഗ്ലോബൽ എറർ ഹാൻഡ്ലിംഗ് മെക്കാനിസങ്ങൾ പരിഗണിക്കാനും ഓർമ്മിക്കുക. പരാജയത്തിനായി രൂപകൽപ്പന ചെയ്യാനും പിശകുകളിൽ നിന്ന് ഭംഗിയായി കരകയറാൻ നിങ്ങളുടെ ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കാനും എപ്പോഴും ഓർമ്മിക്കുക.